#!/usr/bin/env python
"""
ab.py - main file for AsciiBlast

Copyright 2008 Roberto Nerici <roberton [at] bloggo.org>

This file is part of AsciiBlast.
AsciiBlast is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
"""

import curses
import getopt
import sys
import random
import time

from logger import Logger
from game import Game


def do_game(stdscr, autopilot_on, speed_up):
    """
    Initialise and then run the main game loop.
    """
    # Make some checks on the geometry of the available console
    screen_y, screen_x = stdscr.getmaxyx()
    if screen_y < Game.SCREEN_MINHEIGHT or screen_x < Game.SCREEN_MINWIDTH:
        # Not big enough, throw a suitable exception
        errorstring = "Incorrect terminal size," \
            "minimum size is %d x %d, actual size is %d x %d" % \
            (Game.SCREEN_MINWIDTH, Game.SCREEN_MINHEIGHT, screen_x, screen_y)
        raise ValueError, errorstring

    curses.init_pair(1, curses.COLOR_RED, curses.COLOR_BLACK)
    curses.init_pair(2, curses.COLOR_CYAN, curses.COLOR_BLACK)
    curses.init_pair(3, curses.COLOR_YELLOW, curses.COLOR_BLACK)
    random.seed(1)

    log = Logger()

    stdscr.timeout(0)
    stdscr.nodelay(1)
    curses.nl()
    curses.curs_set(0)      # turns off the visible cursor
    game = Game(stdscr, autopilot_on)
    game.draw()
    initial_time = time.time()  # time seconds as a real number
    tick_count = 0
    tick_interval = 50      # game runs in 50ms steps (20Hz)
    timed_game_end = False  # time-limited game ended
    log.log("start of game loop")

    # start the game loop here
    while (not game.over() and not timed_game_end):
        ch = stdscr.getch()
        if ch == ord('q') or ch == ord('Q'):
            return 0
        elif ch == ord('p'):
            do_pause(game)
        else:
            game.handle_key(ch)

        tick_count += tick_interval
        secs_elapsed_total = time.time() - initial_time
        ms_elapsed_total = int(secs_elapsed_total * 1000)
        target_real_ms = tick_count / speed_up
        ms_to_wait = max(0, target_real_ms - ms_elapsed_total)

        log.log("a: target = %d, elapsed = %d, wait = %d" % \
            (target_real_ms, ms_elapsed_total, ms_to_wait))
        curses.napms(ms_to_wait)
        log.log("b: tick_count = " + str(tick_count))
        game.tick(tick_count)
        if autopilot_on and tick_count > 10000:  # 10 seconds
            timed_game_end = True
        game.draw()


def do_pause(game):
    """Implements pause mode - we just block until a key is pressed"""
    stdscr = game.stdscr
    stdscr.nodelay(0)       # turn on blocking input
    game_is_paused = True

    pause_string = "P A U S E D"
    stdscr.addstr(game.screen_height / 2 - 2,
                  (game.screen_width - len(pause_string)) / 2,
                  pause_string,
                  curses.A_BOLD)

    while (game_is_paused):
        stdscr.getch()
        game_is_paused = False
    stdscr.nodelay(1)       # turn off blocking input

def print_version():
    """Displays the version number of the game."""
    print "AsciiBlast version 0.0.3"

def print_help():
    """Display the command line options."""
    print "AsciiBlast: alien assault shoot-em-up in glorious text mode!"
    print "Usage information:"
    print "-a (or --autopilot): let the autopilot play the game."
    print "-h (or --help): show this information."
    print "-l (or --license): show licensing information."
    print "-s (or --speedup) <factor>: make game run faster by 'factor' times."
    print "-v (or --version): show version information."
    print "No options: plays the game!"

def print_license():
    """Display the license."""
    print "AsciiBlast is licensed under",
    print "the GNU General Public License version 3."

# Initial "main": check command line
def eval_cmd_line(params):
    """
    Evaluate command line options.

    Returns True/False to indicate if the game should start.
    For example, --license will mean the license is shown and the program
    should exit (False), while --autopilot will mean the game engine will
    run (True).
    """
    try:
        opts, _ = getopt.getopt(sys.argv[1:], "vlhas:",
                                   ["version", "license", "help",
                                   "autopilot", "speedup:"])
    except getopt.GetoptError, err:
        # print help information and exit:
        print str(err) # will print something like "option -x not recognized"
        print_help()
        sys.exit(2)

    for option, arg in opts:
        if option in ("-h", "--help"):
            print_help()
            return False
        elif option in ("-v", "--version"):
            print_version()
            return False
        elif option in ("-l", "--license"):
            print_license()
            return False
        elif option in ("-a", "--autopilot"):
            params.autopilot = True
        elif option in ("-s", "--speedup"):
            params.speed_factor = int(arg)
        else:
            return False
    return True


class Params:
    """Basic structure to collect the run-time parameters."""
    autopilot = False
    speed_factor = 1    # run at normal speed by default


userparams = Params()
do_play_game = eval_cmd_line(userparams)
if do_play_game:
    if userparams.autopilot:
        if userparams.speed_factor < 1 or userparams.speed_factor > 10:
            userparams.speed_factor = 1
            
    # Play the game! This runs the main game function via a wrapper function
    # provided by the curses library which handles setting and restoring
    # curses settings.
    try:
        curses.wrapper(do_game, userparams.autopilot, userparams.speed_factor)
    except ValueError, error_string:
        print error_string
        

